----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    02:20:45 10/01/2009 
-- Design Name: 
-- Module Name:    program_tx - arch 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity program_tx is
  port ( data_in        : in  std_logic_vector (127 downto 0);
         clk            : in  std_logic;
         reset          : in  std_logic;
         w_data         : out std_logic_vector (7 downto 0);
         tx_full        : in  std_logic;
         wr_uart        : out std_logic;
         data_available : in  std_logic;
         data_ack       : out std_logic);
end program_tx;

architecture arch of program_tx is

  type statetype is ( S1, S2, S3, S4, S5 );
  signal state, next_state : statetype := S1;

  signal data_buffer_store : std_logic_vector(127 downto 0);
  signal data_buffer       : std_logic_vector(127 downto 0);
  signal checksum          : std_logic_vector(7 downto 0);

  signal line_counter : std_logic_vector (5 downto 0) := (others => '0');

begin


  state <= next_state;

  process (clk, reset) is
  begin
    if (reset = '1') then
      next_state   <= S1;
      line_counter <= (others => '0');

    elsif (rising_edge(clk)) then
      case state is

        when S1 =>

          wr_uart      <= '0';
          w_data       <= (others => '0');
          if (data_available = '0') then
            next_state <= S1;
          else
            next_state <= S2;
            data_ack   <= '1';
          end if;

        when S2 =>

          data_ack          <= '0';
          data_buffer_store <= data_in;
          data_buffer       <= data_in;
          line_counter      <= (others => '0');
          checksum          <= (others => '0');
          if (data_available = '1') then
            next_state      <= S2;
          else
            next_state      <= S3;
          end if;

        when S3                     =>
                                        -- Calculate the checksum
          if (line_counter = "010000") then
            next_state   <= S4;
            line_counter <= (others => '0');
            data_buffer  <= data_buffer_store;
          else
            checksum     <= checksum + data_buffer(127 downto 120);
            data_buffer  <= data_buffer(119 downto 0) & "00000000";
            line_counter <= line_counter + 1;
            next_state   <= S3;
          end if;

        when S4 =>

          if (tx_full = '0') then
            wr_uart         <= '1';
            if (line_counter = "000000") then
              w_data        <= x"00";
                                                  -- Test for position 1 to 3
              next_state    <= S5;
            elsif (line_counter(5 downto 1) = "0001" or line_counter = "000001") then
              w_data        <= x"00";
              next_state    <= S5;
            elsif (line_counter = "010100") then  -- Checksum
              w_data        <= checksum;
              next_state    <= S5;
            elsif (line_counter = "010101") then  -- Trailer
              w_data        <= (others => '1');
              next_state    <= S1;
            else
              --if (line_counter /= "010110") then
                w_data      <= data_buffer(127 downto 120);
                data_buffer <= data_buffer(119 downto 0) & "00000000";
                next_state  <= S5;
              --else
              --  next_state  <= S1;
              --end if;
            end if;
            line_counter    <= line_counter + 1;
          else
            next_state      <= S4;
          end if;

        when S5 =>
          wr_uart    <= '0';
          next_state <= S4;

      end case;

    end if;
  end process;


end arch;

